package ru.amse.stroganova.ui.tool.state;

import java.awt.Point;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;

import ru.amse.stroganova.presentation.VertexPresentation;
import ru.amse.stroganova.ui.GraphComponent;
import ru.amse.stroganova.ui.command.Command;
import ru.amse.stroganova.ui.tool.Tool;

/**
 * Basic selection state.
 * 
 * @author Dasha Stroganova
 *
 */
public class SelectionState extends ToolState {

	/**
	 * Component
	 */
	protected final GraphComponent component;

	private Point startPoint;

	private Point tmpStartPoint;
	
	/**
	 * Tool
	 */
	protected final Tool tool;

	private boolean isInSelectedItem;
	
	private final Map<VertexPresentation, Point> beforeDragPositions;
	
	/**
	 * Constructs new default state.
	 * 
	 * @param component
	 * @param parentTool
	 */
	public SelectionState(GraphComponent component, Tool parentTool) {
		this.component = component;
		tool = parentTool;
		isInSelectedItem = false;
		beforeDragPositions = new HashMap<VertexPresentation, Point>();
	}
	
	@Override
	public void mousePressed(MouseEvent e) {
		startPoint = e.getPoint();
		tmpStartPoint = e.getPoint();
		isInSelectedItem = component.getGraphElementSelection().isInSelectedItem(e.getPoint());
		if (!isInSelectedItem && !isCtrlPressed(e)) {
			component.getGraphElementSelection().unselect();
		}
		if (!component.getGraphElementSelection().select(e.getPoint())) {
			tool.setState(new RectangleSelectionState(component, tool, e.getPoint(), this));
		}
		if (!component.getGraphElementSelection().getSelectedVertices().isEmpty()) {
			for (VertexPresentation vp : component.getGraphElementSelection().getSelectedVertices()) {
				beforeDragPositions.put(vp, vp.getCenter());
			}
		}
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		if (isCtrlPressed(e) && isInSelectedItem) {
			component.getGraphElementSelection().unselectItem(e.getPoint());
		} else {
			if (!isCtrlPressed(e)) {
				component.getGraphElementSelection().unselect();
			}
			component.getGraphElementSelection().select(e.getPoint());
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		if (((startPoint.x - e.getPoint().x) != 0)
					|| ((startPoint.y - e.getPoint().y) != 0)) {
			if (!component.getGraphElementSelection().getSelectedVertices().isEmpty()) {
			//TODO when autoscrolling is done and negative coordinates are allowed change it
				Command command = component.getCommandFactory()
						.getNewDragCommand(beforeDragPositions);
				component.addCommand(command);
				command.execute();
				beforeDragPositions.clear();
			}
		}
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		int dx = e.getPoint().x - tmpStartPoint.x;
		int dy = e.getPoint().y - tmpStartPoint.y;
		component.getGraphElementSelection().moveSelectedVertex(dx, dy);
		tmpStartPoint = e.getPoint();
	}
	
	private boolean isCtrlPressed(MouseEvent e) {
		return ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK);
	}
}
